/**
 * Project 68th
 */


#include "TcpConnection.h"
#include "EventLoop.h"
#include <sstream>
#include "Message.h"
#include "LogUtils.h"
using std::ostringstream;

/**
 * TcpConnection implementation
 */


/**
 * @param fd
 */
TcpConnection::TcpConnection(int fd,EventLoop * loop) 
: _loop(loop)
, _sockIO(fd)
, _sock(fd)
, _localAddr(getLocalAddr())
, _peerAddr(getPeerAddr())
{

}

TcpConnection::~TcpConnection() {

}

// /**
//  * @return String
//  */
// String TcpConnection::receive() {
//     char buff[65535] = {0};
//     _sockIO.readLine(buff,sizeof(buff));
//     return string(buff);
// }

/**
 * @return Message
 */
// 假设 MAX_ALLOWED_LENGTH 是一个合理的限制，防止恶意客户端发送超大消息
#define MAX_ALLOWED_LENGTH (1024 * 1024 * 10) // 例如 10MB

Message TcpConnection::receive() {
    Message msg;
    char header_buf[8] = {0}; // 4 bytes for tag, 4 bytes for length
    
    // ----------------------------------------------------------------------
    // 步骤 1: 读取头部 (8 字节)
    // ----------------------------------------------------------------------
    // 必须使用 readn 确保读取 8 字节
    int ret = _sockIO.readn(header_buf, 8);
    
    if (ret == 0) {
        // 连接关闭，这是正常情况
        throw std::runtime_error("Connection closed while reading header.");
    }
    if (ret != 8) {
        // 发生错误或只读取到部分数据（半包/断连）
        throw std::runtime_error("Failed to read complete 8-byte header.");
    }

    // ----------------------------------------------------------------------
    // 步骤 2: 字节序转换与解析
    // ----------------------------------------------------------------------
    uint32_t net_tag, net_len;
    
    // 从缓冲区取出网络字节序的整数
    std::memcpy(&net_tag, header_buf, 4);
    std::memcpy(&net_len, header_buf + 4, 4);
    
    // 转换到主机字节序 (ntohl) 并赋值给 Message
    msg.tag = (int)ntohl(net_tag);
    msg.length = (int)ntohl(net_len);
    
    // ----------------------------------------------------------------------
    // 步骤 3: 安全检查与分配空间
    // ----------------------------------------------------------------------
    if (msg.length <= 0 || msg.length > MAX_ALLOWED_LENGTH) { 
        // 消息长度无效或过大，应断开连接并报告错误
        throw std::runtime_error("Invalid or excessive message length received.");
    }
    
    // 为 value 预留空间
    std::string value_buf(msg.length, '\0'); 
    
    // ----------------------------------------------------------------------
    // 步骤 4: 读取消息体 (msg.length 字节)
    // ----------------------------------------------------------------------
    // 必须使用 readn 确保读取完整的消息体
    // 注意：我们将数据直接读入 string 内部的缓冲区
    ret = _sockIO.readn(&value_buf[0], msg.length);
    if (ret != msg.length) {
        // 消息体读取不完整
        throw std::runtime_error("Message body read incomplete.");
    }
    
    // ----------------------------------------------------------------------
    // 步骤 5: 返回 Message
    // ----------------------------------------------------------------------
    msg.value = std::move(value_buf); // 高效利用移动语义
    
    return msg;
}

/**
 * @param msg
 * @return void
 */

// void TcpConnection::send(const string & msg) {
//     _sockIO.writen(msg.c_str(),msg.size());
// }

void TcpConnection::send(const Message & msg) {
    // 1. 字节序转换（主机序 -> 网络序）
    uint32_t net_tag = htonl(msg.tag);
    uint32_t net_len = htonl(msg.value.size()); 

    // 2. 构造完整的发送缓冲区 (Tag + Length + Value)
    size_t total_size = 8 + msg.value.size();
    std::vector<char> send_buffer(total_size);
    
    // 拷贝头部数据
    std::memcpy(send_buffer.data(), &net_tag, 4);
    std::memcpy(send_buffer.data() + 4, &net_len, 4);
    
    // 拷贝消息体数据
    if (msg.value.size() > 0) {
        std::memcpy(send_buffer.data() + 8, msg.value.c_str(), msg.value.size());
    }
    
    // 3. 调用底层的 writen 确保完整发送
    if (_sockIO.writen(send_buffer.data(), send_buffer.size()) != (ssize_t)send_buffer.size()) {
        // 这里应该记录日志或抛出异常
        throw std::runtime_error("TcpConnection send error: short write or connection closed.");
    }
}

void TcpConnection::sendInLoop(const Message & msg)
{
    if(_loop)
    {
        _loop->runInLoop(bind(&TcpConnection::send,this,msg));
    }
}

string TcpConnection::toString()
{
    ostringstream oss;
    oss << _localAddr.getIp() << ":"
        << _localAddr.getPort() << " -> "
        << _peerAddr.getIp() << ":"
        << _peerAddr.getPort();
    return oss.str();
}

InetAddress TcpConnection::getLocalAddr()
{
    struct sockaddr_in addr;
    socklen_t len = sizeof(addr);

    int ret = getsockname(_sock.getFd(),(struct sockaddr*)&addr,&len);
    if(ret < 0)
    {
        perror("getsockname");
    }

    return InetAddress(addr);
}

InetAddress TcpConnection::getPeerAddr()
{
    struct sockaddr_in addr;
    socklen_t len = sizeof(addr);

    int ret = getpeername(_sock.getFd(),(struct sockaddr*)&addr,&len);
    if(ret < 0)
    {
        perror("getpeername");
    }

    return InetAddress(addr);
}

//先进行一次复制式的预读取
//如果读到的字符数为0，说明客户端下线了
bool TcpConnection::isClosed()
{
    char buff[5] = {0};
    int ret = ::recv(_sock.getFd(),buff,sizeof(buff),MSG_PEEK);
    return ret == 0;
}


void TcpConnection::setNewConnectionCallback(const TcpConnectionCallback & cb)
{
    //如果此处使用移动赋值，那么创建的第一个TcpConnection中
    //的function就会抢占EventLoop中function原本关联的目标
    //这样的话，第二次建立连接时，EventLoop中的function已经是
    //空的function，再做转接工作，第二个TcpConnection的function
    //也会是空的function，并没有正确地注册回调函数

    /* _onNewConnection = std::move(cb); */
    _onNewConnection = cb;
}
void TcpConnection::setMessageCallback(const TcpConnectionCallback & cb)
{
    _onMessage = cb;
}
void TcpConnection::setCloseCallback(const TcpConnectionCallback & cb)
{
    _onClose = cb;
}

void TcpConnection::handleNewConnectionCallback()
{
    if(_onNewConnection){
        /* _onNewConnection(shared_ptr<TcpConnection>(this)); */
        _onNewConnection(shared_from_this());
    }
    else
    {
        printf("_onNewConnection是空的function\n");
    }
}
void TcpConnection::handleMessageCallback()
{
    if(_onMessage){
        _onMessage(shared_from_this());
    }
    else
    {
        printf("_onMessage是空的function\n");
    }
}
void TcpConnection::handleCloseCallback()
{
    if(_onClose){
        _onClose(shared_from_this());
    }
    else
    {
        printf("_onClose是空的function\n");
    }
}
